PostgreSQL 安全管理 文件读取攻击

1 背景知识

为了方便在PG上开发管理和运维,PG提供了一系列数据库管理函数。所有的管理函数参见 9.27. 系统管理函数 (postgres.cn)

但是由于不正确的设置,导致数据库容易收到攻击和破坏。

攻击方向有两个:
1、adminpack 插件设置不合理。
2、数据库管理函数设置不合理。

本章主要从以上两方面介绍如何打造一个安全的postgresql 数据库。

2 pg_read_file() 函数

1、这个函数可以访问数据库文件和操作系统文件。
2、默认状态下: 可以访问数据库集簇目录和 log_directory 文件。
3、当用户授予了 pg_read_server_files 时,可以访问操作系统文件。
4、当将 pg_read_file() 函数的EXECUTE 权限授予其他用户时。此用户可以绕过数据库内的权限检查,并读取数据库集簇目录中任何文件。
5、所以设置此类函数需要慎重。

2.1 将操作系统文件拷贝到 pg_log 目录下

\c - postgres
\! cp /etc/passwd $PGDATA/pg_log

2.2 将 pg_read_file 函数的执行权限授予 user01

\c - postgres
GRANT EXECUTE ON FUNCTION pg_read_file(text) TO user01;

2.3 使用user01 用户读取文件

1、读取操作系统文件: 失败。
2、数据库集簇文件:成功执行。

\c - user01
SELECT pg_read_file('pg_log/passwd');
//屏幕输出:
                           pg_read_file
--------------------------------------------------------------------
 root:x:0:0:root:/root:/bin/bash                                   +
 bin:x:1:1:bin:/bin:/sbin/nologin                                  +
 daemon:x:2:2:daemon:/sbin:/sbin/nologin                           +
 adm:x:3:4:adm:/var/adm:/sbin/nologin                              +
......
(1 row)

SELECT pg_read_file('/etc/passwd');
//屏幕输出:
ERROR:  absolute path not allowed

2.4 将 pg_read_server_files 权限授予 user01

\c - postgres
GRANT pg_read_server_files TO user01;

2.5 使用user01 用户读取文件

读取操作系统文件还是数据库集簇文件都可以成功执行。

\c - user01;
SELECT pg_read_file('pg_log/passwd');
//屏幕输出:
                           pg_read_file
--------------------------------------------------------------------
 root:x:0:0:root:/root:/bin/bash                                   +
 bin:x:1:1:bin:/bin:/sbin/nologin                                  +
 daemon:x:2:2:daemon:/sbin:/sbin/nologin                           +
 adm:x:3:4:adm:/var/adm:/sbin/nologin                              +
......
(1 row)


SELECT pg_read_file('/etc/passwd');
//屏幕输出:
                           pg_read_file
--------------------------------------------------------------------
 root:x:0:0:root:/root:/bin/bash                                   +
 bin:x:1:1:bin:/bin:/sbin/nologin                                  +
 daemon:x:2:2:daemon:/sbin:/sbin/nologin                           +
 adm:x:3:4:adm:/var/adm:/sbin/nologin                              +
......
(1 row)

SELECT pg_read_file('/etc/passwd');

3 COPY 命令

影响范围,见 [[#2 pg_read_file() 函数]]。
对于使用 COPY命令 使用条件: 超级用户或者 pg_read_server_files 角色。

DROP TABLE IF EXISTS t01;
CREATE TABLE T01 (info text);
COPY T01 FROM '/etc/passwd';
SELECT * FROM t01;

4 pg_read_server_files 角色

见 [[#2 pg_read_file() 函数]]。

5 pg_execute_server_program 角色

6 小结

1、不要轻易赋予用户foreign server的usage权限和pg_read_server_files角色,否则数据库用户将可以查看服务器上的各种数据库文件。

2、不要轻易赋予用户foreign server的usage权限和pg_execute_server_program角色,否则数据库用户将可以删除整个数据库,或者拷贝走全部数据。